home *** CD-ROM | disk | FTP | other *** search
- #include "acedef.h"
- #include <string.h>
- #include <clib/dos_protos.h>
- #include <clib/intuition_protos.h>
-
- /* local variables */
- extern struct Remember *GenRememberList;
- extern struct Remember *SymRememberList[2];
-
- /* Externals */
-
- extern int lev;
- extern int sym;
- extern int typ;
- extern int errors;
- extern int exitvalue;
- extern int addr[2];
- extern char string_const_start[7];
- extern char string_const_end[4];
- extern char id[MAXIDSIZE];
- extern char exit_sub_name[80];
- extern FILE *dest;
- extern SYM *curr_item;
- extern CODE *curr_code;
- extern BOOL early_exit;
- extern BOOL optimise_opt;
- extern BOOL module_opt;
- extern BOOL cli_args;
- extern BOOL translateused;
- extern BOOL mathffpused;
- extern BOOL mathtransused;
- extern BOOL gfxused;
- extern BOOL intuitionused;
- extern BOOL iffused;
- extern BOOL ontimerused;
- extern BOOL narratorused;
- extern BOOL basdatapresent;
- extern BOOL readpresent;
- extern BOOL make_icon;
- extern BOOL end_of_source;
-
- /* locals */
- static char *frame_ptr[] ={"(a4)", "(a5)"};
-
- /* functions alloc.c */
- void *alloc (unsigned int bytes, unsigned long flags)
- {
- /* allocate memory as requested */
-
- return ((void *) AllocRemember (&GenRememberList, bytes, flags));
- }
-
- void *sym_alloc (unsigned int bytes, unsigned long flags)
- {
- /* allocate memory for current level's symbol table as requested */
-
- return ((void *) AllocRemember (&SymRememberList[lev], bytes, flags));
- }
-
-
- /* functions assign.c */
- void make_data_const (char *string)
- {
- char *strbuf;
-
- /* actual string constant */
- strbuf = (char *) alloc (strlen (string) + 10L, MEMF_ANY);
- /* +10 is for string_const_start/end (9) & '\0' */
- strcpy (strbuf, string_const_start);
- strcat (strbuf, string);
- strcat (strbuf, string_const_end);
- enter_BASDATA (strbuf);
- /*FreeMem(strbuf,strlen(string)+10); */
- }
-
-
- BOOL search_func (char *bmap, char *func, SYM * declared_func)
- {
- /*
- ** Search for function in .bmap file, recording register usage
- ** and library base offset in symbol table entry for function.
- */
-
- unsigned char *buf;
- struct FileHandle *f;
- unsigned char ch, name[MAXIDSIZE];
- long bmap_size = 5000, count, cc, rc;
- SHORT offset = 0;
- BOOL found = FALSE;
-
- {
- f = (struct FileHandle *) Open ((STRPTR) bmap, MODE_OLDFILE);
-
- if( !f )
- {
- _error( 50 );
- return FALSE;
- }
-
- Seek( (BPTR) f, 0, OFFSET_END );
- bmap_size = Seek( (BPTR) f, 0, OFFSET_BEGINNING );
-
- /* read whole bmap file into a buffer */
- buf = (unsigned char *) alloc (bmap_size, MEMF_ANY);
-
- Read ((BPTR) f, buf, bmap_size);
- Close ((BPTR) f);
-
- count = 0; /* start of buffer */
-
- while (!found && count < bmap_size)
- {
- /* build function name */
- cc = 0;
- while (count < bmap_size && cc < MAXIDSIZE)
- {
- ch = name[cc++] = buf[count++];
- if (ch == '\0')
- break; /* exit loop when EOS reached */
- }
-
- name[cc - 1] = '\0'; /* make sure we have an EOS symbol (may exit early) */
-
- if (strcmp ((char *) name, func) != 0)
- {
- /* skip 2-byte offset */
- count += 2;
- /* skip to next name */
- while (count < bmap_size && (ch = buf[count++]) != '\0');
- }
- else
- found = TRUE; /* that's it! -> get the info' */
- }
-
- if (!found)
- return (FALSE);
-
- /* get library base offset (2 bytes) */
- if (count < bmap_size)
- {
- ch = buf[count++];
- offset += ch * 256;
- }
- else
- return (FALSE);
-
- if (count < bmap_size)
- {
- ch = buf[count++];
- offset += ch;
- }
- else
- return (FALSE);
-
- declared_func->address = (SHORT) offset; /* record library base offset */
-
- /* get n bytes of register data */
- declared_func->reg = (UBYTE *) sym_alloc (15, MEMF_ANY);
- if (declared_func->reg == NULL)
- {
- puts ("Can't allocate memory for function register info!");
- early_exit = TRUE;
- kill_all_lists ();
- cleanup ();
- }
-
- rc = 0;
- while (count < bmap_size &&
- (ch = buf[count++]) != '\0')
- declared_func->reg[rc++] = ch;
-
- declared_func->no_of_params = rc; /* record no. of parameters */
-
- if (ch != '\0')
- return (FALSE); /* last character should be NULL */
-
- /* we found it -> return */
- return (TRUE);
- }
- }
-
- /* functions misc.c */
-
- void push_num_constant (int typ, SYM * item)
- {
- /* push a numeric
- constant onto
- the stack.
- */
- char buf[40], numbuf[40];
-
- strcpy (numbuf, "#\0");
- switch (typ)
- {
- case shorttype:
- itoa (item->numconst.shortnum, buf, 10L);
- break;
- case longtype:
- ltoa (item->numconst.longnum, buf, 10);
- break;
- case singletype:
- /* sprintf (buf, "%lx", item->numconst.singlenum); original */
- sprintf (buf, "%x", item->numconst.singlenum);
- strcat (numbuf, "$");
- break;
- }
-
- strcat (numbuf, buf);
-
- if (typ == shorttype)
- gen ("move.w", numbuf, "-(sp)");
- else
- gen ("move.l", numbuf, "-(sp)");
- }
-
- /* functions parse.c */
-
- void compile (char *source_name, char *dest_name)
- {
- char buf[40], bytes[40], icon_name[MAXSTRLEN];
- FILE *icon_src, *icon_dest;
- int cc;
-
- /*
- ** Parse the source file producing XREFs, code, data,
- ** bss & basdata segments.
- */
- parse ();
-
- /* optimise? */
- if (optimise_opt && !early_exit)
- optimise ();
-
- if (!module_opt)
- {
- /* startup xrefs for startup.lib */
- enter_XREF ("_startup");
- enter_XREF ("_cleanup");
-
- /* command line argument xref */
- if (cli_args)
- enter_XREF ("_parse_cli_args");
-
- if (translateused)
- {
- enter_XREF ("_opentranslator");
- enter_XREF ("_closetranslator");
- }
-
- if (mathffpused)
- {
- enter_XREF ("_openmathffp");
- enter_XREF ("_closemathffp");
- }
-
- if (mathtransused)
- {
- enter_XREF ("_openmathtrans");
- enter_XREF ("_closemathtrans");
- }
-
- if (gfxused)
- {
- enter_XREF ("_opengfx");
- enter_XREF ("_closegfx");
- enter_XREF ("_openintuition");
- enter_XREF ("_closeintuition");
- }
-
- if (intuitionused)
- {
- enter_XREF ("_openintuition");
- enter_XREF ("_closeintuition");
- }
-
- if (iffused)
- {
- enter_XREF ("_create_ILBMLib");
- enter_XREF ("_remove_ILBMLib");
- }
-
- enter_XREF ("_starterr");
-
- /*
- ** A module may need to jump to _EXIT_PROG so
- ** make this label externally referenceable (* = XDEF).
- */
- enter_XREF ("*EXIT_PROG");
-
- if (ontimerused)
- enter_XREF ("_ontimerstart");
-
- /*
- ** Always call this in case a db.lib function
- ** allocates memory via alloc(). This also takes
- ** care of the use of ALLOC by an ACE program.
- ** To do this we always need to externally
- ** reference the free_alloc() function.
- */
- enter_XREF ("_free_alloc");
- }
- else
- {
- /*
- ** Current module may need to jump to _EXIT_PROG, so externally reference it.
- */
- enter_XREF ("_EXIT_PROG");
- }
-
- /* DATA statements? */
- if (basdatapresent)
- enter_BSS ("_dataptr:", "ds.l 1");
- if ((readpresent) && (!basdatapresent))
- _error (25);
-
- /* ------------------------------------------------- */
- /* create A68K compatible 68000 assembly source file */
- /* ------------------------------------------------- */
-
- if (!early_exit)
- printf ("\ncreating %s\n", dest_name);
- else
- printf ("\nfreeing code list...\n");
-
- if (!early_exit)
- write_xrefs ();
-
- /* startup code */
- fprintf (dest, "\n\tSECTION code,CODE\n\n");
-
- if (!module_opt)
- {
- /*
- ** Check for Wb start BEFORE DOING ANYTHING ELSE!
- ** This also always opens dos.library and stores
- ** CLI argument data.
- */
- fprintf (dest, "\tjsr\t_startup\n");
- fprintf (dest, "\tcmpi.b\t#1,_starterr\n"); /* see _startup in startup.lib */
- fprintf (dest, "\tbne.s\t_START_PROG\n");
- fprintf (dest, "\trts\n");
- fprintf (dest, "_START_PROG:\n");
-
- /* storage for initial stack pointer */
- enter_BSS ("_initialSP:", "ds.l 1");
- fprintf (dest, "\tmove.l\tsp,_initialSP\n"); /* save task's stack pointer */
-
- fprintf (dest, "\tmovem.l\td1-d7/a0-a6,-(sp)\n"); /* save initial registers */
-
- if (cli_args)
- fprintf (dest, "\tjsr\t_parse_cli_args\n"); /* get CLI arguments */
-
- if (translateused)
- {
- fprintf (dest, "\tjsr\t_opentranslator\n");
- fprintf (dest, "\tcmpi.b\t#1,_starterr\n");
- fprintf (dest, "\tbne.s\t_translate_ok\n");
- fprintf (dest, "\tjmp\t_ABORT_PROG\n");
- fprintf (dest, "_translate_ok:\n");
- }
-
- if (mathffpused)
- {
- fprintf (dest, "\tjsr\t_openmathffp\n");
- fprintf (dest, "\tcmpi.b\t#1,_starterr\n");
- fprintf (dest, "\tbne.s\t_mathffp_ok\n");
- fprintf (dest, "\tjmp\t_ABORT_PROG\n");
- fprintf (dest, "_mathffp_ok:\n");
- }
-
- if (mathtransused)
- {
- fprintf (dest, "\tjsr\t_openmathtrans\n");
- fprintf (dest, "\tcmpi.b\t#1,_starterr\n");
- fprintf (dest, "\tbne.s\t_mathtrans_ok\n");
- fprintf (dest, "\tjmp\t_ABORT_PROG\n");
- fprintf (dest, "_mathtrans_ok:\n");
- }
-
- if (intuitionused && !gfxused)
- {
- fprintf (dest, "\tjsr\t_openintuition\n");
- fprintf (dest, "\tcmpi.b\t#1,_starterr\n");
- fprintf (dest, "\tbne.s\t_intuition_ok\n");
- fprintf (dest, "\tjmp\t_ABORT_PROG\n");
- fprintf (dest, "_intuition_ok:\n");
- }
-
- if (gfxused)
- {
- /* open intuition.library */
- fprintf (dest, "\tjsr\t_openintuition\n");
- fprintf (dest, "\tcmpi.b\t#1,_starterr\n");
- fprintf (dest, "\tbne.s\t_intuition_ok\n");
- fprintf (dest, "\tjmp\t_ABORT_PROG\n");
- fprintf (dest, "_intuition_ok:\n");
-
- /* open graphics.library */
- fprintf (dest, "\tjsr\t_opengfx\n");
- fprintf (dest, "\tcmpi.b\t#1,_starterr\n");
- fprintf (dest, "\tbne.s\t_gfx_ok\n");
- fprintf (dest, "\tjmp\t_ABORT_PROG\n");
- fprintf (dest, "_gfx_ok:\n");
- }
-
- /* create temporary ILBM.library */
- if (iffused)
- fprintf (dest, "\tjsr\t_create_ILBMLib\n");
-
- /* get timer event trapping start time */
- if (ontimerused)
- fprintf (dest, "\tjsr\t_ontimerstart\n");
-
- /* size of stack frame */
- if (addr[lev] == 0)
- strcpy (bytes, "#\0");
- else
- strcpy (bytes, "#-");
- itoa (addr[lev], buf, 10L);
- strcat (bytes, buf);
-
- /* create stack frame */
- fprintf (dest, "\tlink\ta4,%s\n\n", bytes);
-
- /* initialise global DATA pointer */
- if (basdatapresent)
- fprintf (dest, "\tmove.l\t#_BASICdata,_dataptr\n");
- }
-
- /* write code & kill code list */
- kill_code ();
-
- if (!module_opt)
- {
- /* exiting code */
- fprintf (dest, "\n_EXIT_PROG:\n");
-
- fprintf (dest, "\tunlk\ta4\n");
-
- /*
- ** Programs which abort should cleanup libraries, free allocated memory
- ** and possibly reply to a Wb startup message.
- */
- if (intuitionused || gfxused || mathffpused || mathtransused ||
- translateused)
- fprintf (dest, "_ABORT_PROG:\n");
-
- /* Free memory allocated via ALLOC and db.lib calls to alloc(). */
- fprintf (dest, "\tjsr\t_free_alloc\n");
-
- /* close libraries */
- if (gfxused)
- {
- fprintf (dest, "\tjsr\t_closegfx\n");
- fprintf (dest, "\tjsr\t_closeintuition\n");
- }
- if (narratorused)
- fprintf (dest, "\tjsr\t_cleanup_async_speech\n");
- if (intuitionused && !gfxused)
- fprintf (dest, "\tjsr\t_closeintuition\n");
- if (mathtransused)
- fprintf (dest, "\tjsr\t_closemathtrans\n");
- if (mathffpused)
- fprintf (dest, "\tjsr\t_closemathffp\n");
- if (translateused)
- fprintf (dest, "\tjsr\t_closetranslator\n");
-
- /* delete temporary ILBM.library */
- if (iffused)
- fprintf (dest, "\tjsr\t_remove_ILBMLib\n");
-
- /* restore registers */
- fprintf (dest, "\tmovem.l\t(sp)+,d1-d7/a0-a6\n");
-
- /* restore initial stack pointer */
- fprintf (dest, "\tmove.l\t_initialSP,sp\n");
-
- /*
- ** Close dos.library and reply to Wb message
- ** as the LAST THING DONE before rts'ing.
- */
- fprintf (dest, "\tjsr\t_cleanup\n");
-
- /* return */
- fprintf (dest, "\n\trts\n");
- }
-
- if (!early_exit)
- {
- write_data ();
- write_basdata ();
- write_bss ();
- }
-
- fprintf (dest, "\n\tEND\n");
-
- /* errors? */
- if (errors > 0)
- putchar ('\n');
-
- printf ("%s compiled ", source_name);
-
- if (errors == 0)
- printf ("with no errors.\n");
- else
- {
- exitvalue = 10; /* set ERROR for bas script */
- printf ("with %d ", errors);
- if (errors > 1)
- printf ("errors.\n");
- else
- printf ("error.\n");
- }
-
- /* make icon? */
- if (make_icon && !early_exit)
- {
- if ((icon_src = fopen ("ACE:icons/exe.info", "r")) == NULL)
- puts ("can't open ACE:icons/exe.info for reading.");
- else
- {
- cc = 0;
- while (source_name[cc] != '.')
- cc++;
- source_name[cc] = '\0';
- sprintf (icon_name, "%s.info", source_name);
- if ((icon_dest = fopen (icon_name, "w")) == NULL)
- printf ("can't open %s.info for writing.\n", source_name);
- else
- {
- while (!feof (icon_src))
- fputc (fgetc (icon_src), icon_dest);
- fclose (icon_dest);
- fclose (icon_src);
- puts ("icon created.");
- }
- }
- }
- }
-
- void block (void)
- {
- CODE *link;
- SYM *sub_ptr;
- char end_of_sub_name[80], end_of_sub_label[80];
- char sub_name[80], sub_label[80], exit_sub_label[80];
- char xdef_name[80];
- char bytes[40], buf[40];
- int subprog;
- int sub_type, def_expr_type;
-
- while (!end_of_source)
- {
- if (sym != subsym && sym != defsym)
- /* ordinary statement */
- statement ();
- else
- {
- /************************/
- /* SUBprogram or DEF FN */
- /************************/
- subprog = sym;
- insymbol ();
-
- sub_type = undefined;
-
- /* type identifiers */
- if (sym == shortintsym || sym == longintsym || sym == addresssym ||
- sym == singlesym || sym == stringsym)
- {
- switch (sym)
- {
- case shortintsym:
- sub_type = shorttype;
- break;
- case longintsym:
- sub_type = longtype;
- break;
- case addresssym:
- sub_type = longtype;
- break;
- case singlesym:
- sub_type = singletype;
- break;
- case stringsym:
- sub_type = stringtype;
- break;
- }
- insymbol ();
- }
-
- if (sym != ident)
- _error (32);
- else
- {
- /* get name of subprogram and prefix _SUB_ to it */
- strcpy (sub_name, "_SUB_");
- strcat (sub_name, id);
-
- if (!exist (sub_name, subprogram))
- {
- if (sub_type == undefined)
- sub_type = typ;
- enter (sub_name, sub_type, subprogram, 0); /* new SUB */
- curr_item->decl = subdecl;
- }
- else if ((exist (sub_name, subprogram)) && (curr_item->decl == fwdref))
- curr_item->decl = subdecl;
- else
- _error (33); /* already exists */
-
- sub_ptr = curr_item; /* pointer to sub info' */
-
- turn_event_off (sub_name); /* see event.c */
-
- /* exit point name & label */
- strcpy (exit_sub_name, "_EXIT");
- strcat (exit_sub_name, sub_name);
- strcpy (exit_sub_label, exit_sub_name);
- strcat (exit_sub_label, ":\0");
-
- /* prepare for level ONE */
- lev = ONE;
- addr[lev] = 0;
- new_symtab ();
- make_label (end_of_sub_name, end_of_sub_label);
- gen ("jmp", end_of_sub_name, " ");
-
- /* subprogram label -> _SUB_ prefix to make it unique */
- strcpy (sub_label, sub_name);
- strcat (sub_label, ":\0");
- gen (sub_label, " ", " ");
-
- /* all SUBs need link instruction -- add # of bytes later */
- gen ("link", "a5", " ");
- link = curr_code;
-
- /* parse formal parameter list */
- sub_params (sub_ptr);
-
- /* make this subprogram externally visible? */
- if (sym == externalsym)
- {
- insymbol ();
- strcpy (xdef_name, sub_name);
- xdef_name[0] = '*'; /* signal that this is an XDEF */
- enter_XREF (xdef_name);
- }
-
- /*
- ** Pass function (SUB) values via d0 for ALL subprograms
- ** in a module since there is no link using A4 for modules.
- */
- if (module_opt)
- sub_ptr->address = extfunc; /* This has a numeric value of 3004:
- hopefully large enough to avoid
- clashes with real stack offsets. */
-
- /* SUB or DEF FN code? */
- if (subprog == subsym)
- {
- while ((sym != endsym) && (!end_of_source))
- {
- if (sym == sharedsym)
- parse_shared_vars ();
- if ((sym != endsym) && (!end_of_source))
- statement ();
- }
-
- if (end_of_source)
- _error (34); /* END SUB expected */
-
- if (sym == endsym)
- {
- insymbol ();
- if (sym != subsym)
- _error (35);
- insymbol ();
- }
- }
- else
- {
- /* DEF FN code */
- if (sym != equal)
- _error (5);
- else
- {
- insymbol ();
- def_expr_type = expr ();
- if (assign_coerce (sub_type, def_expr_type) != sub_type)
- _error (4);
- else if (sub_type == shorttype)
- gen ("move.w", "(sp)+", "d0");
- else
- gen ("move.l", "(sp)+", "d0");
-
- /* change object from SUB to DEF FN */
- sub_ptr->object = definedfunc;
- }
- }
-
- /* establish size of stack frame */
- if (addr[lev] == 0)
- strcpy (bytes, "#\0");
- else
- strcpy (bytes, "#-");
- itoa (addr[lev], buf, 10L);
- strcat (bytes, buf);
- change (link, "link", "a5", bytes);
-
- /* exit code */
- if (subprog == subsym)
- gen (exit_sub_label, " ", " ");
- gen ("unlk", "a5", " ");
- gen ("rts", " ", " ");
- gen (end_of_sub_label, " ", " ");
-
- kill_symtab ();
- lev = ZERO;
- }
- }
- }
- }
-
- /* functions sub.c */
- void load_params (SYM * sub_ptr)
- {
- long par_addr = -8; /* one word above stack frame
- (allows for R.A. & address reg store) */
- SHORT i, n;
- int formal_type;
- char addrbuf[40];
- char formaltemp[MAXPARAMS][80], formaladdr[MAXPARAMS][80];
- int formaltype[MAXPARAMS];
-
- /* store actual parameters in stack frame of subprogram to be CALLed */
-
- if (sym != lparen)
- {
- _error (14);
- return;
- }
- else
- {
- i = 0;
- do
- {
- insymbol ();
- formal_type = expr ();
-
- /* check parameter types */
- if (formal_type != sub_ptr->p_type[i])
- {
- /* coerce actual parameter type to formal parameter type */
- switch (sub_ptr->p_type[i])
- {
- case shorttype:
- make_sure_short (formal_type);
- break;
-
- case longtype:
- if ((formal_type = make_integer (formal_type)) == shorttype)
- make_long ();
- else if (formal_type == notype)
- _error (4); /* string */
- break;
-
- case singletype:
- gen_Flt (formal_type);
- break;
-
- case stringtype:
- _error (4); /* can't coerce this at all! */
- break;
- }
- }
-
- /* store parameter information temporarily since further stack operations
- may corrupt data in next frame if stored immediately */
- if (sub_ptr->p_type[i] == shorttype)
- {
- par_addr -= 2;
- /* save parameter type */
- formaltype[i] = shorttype; /* not data TYPE but STORE type (2 or 4 bytes) */
-
- /* save address of formal */
- itoa (par_addr, addrbuf, 10);
- strcat (addrbuf, "(sp)");
- strcpy (formaladdr[i], addrbuf);
-
- /* create temporary store in current stack frame -> don't use a global
- data object as it could be clobbered during recursion! */
- addr[lev] += 2;
- itoa (-1 * addr[lev], formaltemp[i], 10L);
- strcat (formaltemp[i], frame_ptr[lev]);
-
- /* store it */
- gen ("move.w", "(sp)+", formaltemp[i]);
- }
- else
- /* long, single, string, array */
- {
- par_addr -= 4;
- /* save parameter type */
- formaltype[i] = longtype; /* storage requirement is 4 bytes */
-
- /* save address of formal */
- itoa (par_addr, addrbuf, 10);
- strcat (addrbuf, "(sp)");
- strcpy (formaladdr[i], addrbuf);
-
- /* create temporary store in current stack frame -> don't use a global
- data object as it could be clobbered during recursion! */
- addr[lev] += 4;
- itoa (-1 * addr[lev], formaltemp[i], 10L);
- strcat (formaltemp[i], frame_ptr[lev]);
-
- /* store it */
- gen ("move.l", "(sp)+", formaltemp[i]);
- }
-
- i++;
- }
- while ((i < sub_ptr->no_of_params) && (sym == comma));
-
- if ((i < sub_ptr->no_of_params) || (sym == comma))
- _error (39); /* parameter count mismatch - too few or too many resp. */
- else
- {
- /* disable multi-tasking
- before passing parameters */
- gen ("movea.l", "_AbsExecBase", "a6");
- gen ("jsr", "_LVOForbid(a6)", " ");
- enter_XREF ("_AbsExecBase");
- enter_XREF ("_LVOForbid");
-
- /* load parameters into next frame */
- for (n = 0; n < sub_ptr->no_of_params; n++)
- {
- if (formaltype[n] == shorttype)
- gen ("move.w", formaltemp[n], formaladdr[n]); /* short */
- else
- gen ("move.l", formaltemp[n], formaladdr[n]); /* long,string,single,array */
- }
- }
-
- if (sym != rparen)
- _error (9);
- }
- }
-